﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Entidades;
using System.Data.SqlClient;

namespace AccesoBD
{
    public class RecibosCobroAtencionMedica
    {
        /// <summary>
        /// Obtiene TODOS los tipo de paciente, la idea seria que traiga solo los que le pertenecen al paciente por el cual busco
        /// con su nroHC, pero implicaria realizar cambios en la base de datos (columnas bit tieneOS, tieneAf)
        /// </summary>
        /// <returns>Lista con todos los tipos de paciente</returns>
        public static List<TipoPaciente> obtenerTiposPaciente()
        {
            List<TipoPaciente> lista = null;
            SqlConnection conexion = DB.Conectar();
            try
            {
                string comando = "SELECT idTipoPaciente, nombre, descripcion FROM Tipo_Paciente";
                SqlCommand sqlcmd = new SqlCommand(comando, conexion);
                SqlDataReader dr = sqlcmd.ExecuteReader();
                if (dr.HasRows)
                {
                    lista = new List<TipoPaciente>();
                    TipoPaciente tp = null;
                    while (dr.Read())
                    {
                        tp = new TipoPaciente();
                        tp.IdTipoPaciente = int.Parse(dr["idTipoPaciente"].ToString());
                        tp.Nombre = dr["nombre"].ToString();

                        lista.Add(tp);
                        tp = null;
                    }
                }
            }
            catch (Exception)
            {

                throw;
            }
            finally
            {
                conexion.Close();
            }
            return lista;
        }

        /// <summary>
        /// Obtiene TODOS los tipo de paciente, pero solo los que le perteneces al nroHC que paso por parámetro.
        /// </summary>
        /// <returns>Lista con todos los tipos de paciente que corresponden al nroHC</returns>
        public static List<TipoPaciente> obtenerTiposPaciente(long nroHC)
        {
            List<TipoPaciente> lista = null;
            SqlConnection conexion = DB.Conectar();
            SqlTransaction trans = null;
            try
            {
                trans = conexion.BeginTransaction();

                bool tieneOS = false, tieneAf = false;
                string comando = "SELECT nroHC, tieneOS, tieneAfiliacion FROM Paciente WHERE (nroHC = @nroHC)";
                SqlCommand sqlcmd = new SqlCommand(comando, conexion);
                sqlcmd.Parameters.Add(new SqlParameter("@nroHC", nroHC));
                sqlcmd.Transaction = trans;
                SqlDataReader dr = sqlcmd.ExecuteReader();
                if (dr.HasRows)
                {
                    while (dr.Read())
                    {
                        if (dr["tieneOS"] == DBNull.Value) //no tiene os cargados, suponemos que no las tiene cargada, entonces false
                            tieneOS = false;
                        else
                            tieneOS = bool.Parse(dr["tieneOS"].ToString());
                        if (dr["tieneAfiliacion"] == DBNull.Value) //no tiene afialiacion seteada, suponemos que no tiene, entonces false
                            tieneAf = false;
                        else
                            tieneAf = bool.Parse(dr["tieneAfiliacion"].ToString());
                    }
                }
                dr.Close();

                //ahora traemos de acuerdo a la condicion/es del paciente
                if (tieneAf && tieneOS)
                {
                    comando = "SELECT idTipoPaciente, nombre, descripcion FROM Tipo_Paciente";
                    sqlcmd = new SqlCommand(comando, conexion);
                    sqlcmd.Transaction = trans;
                    dr = sqlcmd.ExecuteReader();
                    if (dr.HasRows)
                    {
                        lista = new List<TipoPaciente>();
                        TipoPaciente tp = null;
                        while (dr.Read())
                        {
                            tp = new TipoPaciente();
                            tp.IdTipoPaciente = int.Parse(dr["idTipoPaciente"].ToString());
                            tp.Nombre = dr["nombre"].ToString();

                            lista.Add(tp);
                            tp = null;
                        }
                    }
                    dr.Close();
                }//fin primer if
                else if (!tieneAf && tieneOS)
                {
                    comando = "SELECT idTipoPaciente, nombre FROM Tipo_Paciente WHERE (idTipoPaciente <> 3)";
                    sqlcmd = new SqlCommand(comando, conexion);
                    sqlcmd.Transaction = trans;
                    dr = sqlcmd.ExecuteReader();
                    if (dr.HasRows)
                    {
                        lista = new List<TipoPaciente>();
                        TipoPaciente tp = null;
                        while (dr.Read())
                        {
                            tp = new TipoPaciente();
                            tp.IdTipoPaciente = int.Parse(dr["idTipoPaciente"].ToString());
                            tp.Nombre = dr["nombre"].ToString();

                            lista.Add(tp);
                            tp = null;
                        }
                    }
                    dr.Close();
                }
                else if (!tieneOS && tieneAf)
                {
                    comando = "SELECT idTipoPaciente, nombre FROM Tipo_Paciente WHERE (idTipoPaciente <> 2)";
                    sqlcmd = new SqlCommand(comando, conexion);
                    sqlcmd.Transaction = trans;
                    dr = sqlcmd.ExecuteReader();
                    if (dr.HasRows)
                    {
                        lista = new List<TipoPaciente>();
                        TipoPaciente tp = null;
                        while (dr.Read())
                        {
                            tp = new TipoPaciente();
                            tp.IdTipoPaciente = int.Parse(dr["idTipoPaciente"].ToString());
                            tp.Nombre = dr["nombre"].ToString();

                            lista.Add(tp);
                            tp = null;
                        }
                    }
                    dr.Close();
                }
                else
                {
                    comando = "SELECT idTipoPaciente, nombre FROM Tipo_Paciente WHERE (idTipoPaciente = 1)"; //solo particular
                    sqlcmd = new SqlCommand(comando, conexion);
                    sqlcmd.Transaction = trans;
                    dr = sqlcmd.ExecuteReader();
                    if (dr.HasRows)
                    {
                        lista = new List<TipoPaciente>();
                        TipoPaciente tp = null;
                        while (dr.Read())
                        {
                            tp = new TipoPaciente();
                            tp.IdTipoPaciente = int.Parse(dr["idTipoPaciente"].ToString());
                            tp.Nombre = dr["nombre"].ToString();

                            lista.Add(tp);
                            tp = null;
                        }
                    }
                    dr.Close();
                }

                trans.Commit();
            }
            catch (Exception)
            {
                trans.Rollback();
                throw;
            }
            finally
            {
                conexion.Close();
            }
            return lista;
        }

        /// <summary>
        /// Busca y obtiene la afiliacion, el plan de afiliacion actual del paciente solicitado, junto con su detalle para tener
        /// también los precios.
        /// </summary>
        /// <param name="nroHC">Número de HC del paciente</param>
        /// <returns>Afiliacion completa del paciente solicitado</returns>
        public static Afiliacion obtenerAfiliacionPaciente(long nroHC)
        {
            Afiliacion afiliacionPaciente = null;
            SqlConnection conexion = DB.Conectar();
            SqlTransaction tran = null;
            try
            {
                tran = conexion.BeginTransaction();
                string comando = "SELECT Afiliado.nroAfiliado, Afiliado.nroHCpaciente, Afiliacion.idAfiliacion, Afiliacion.idPlan, Plan_Afiliacion.nombre "
                                + "FROM Afiliado INNER JOIN Afiliacion ON Afiliado.nroAfiliado = Afiliacion.nroAfiliado INNER JOIN Plan_Afiliacion ON Afiliacion.idPlan = Plan_Afiliacion.idPlan "
                                + "WHERE (Afiliado.nroHCpaciente = @nroHC)";
                SqlCommand sqlcmd = new SqlCommand(comando, conexion);
                sqlcmd.Parameters.Add(new SqlParameter("@nroHC", nroHC));
                sqlcmd.Transaction = tran;
                SqlDataReader dr = sqlcmd.ExecuteReader();
                if (dr.HasRows)
                {
                    afiliacionPaciente = new Afiliacion();
                    while (dr.Read())
                    {
                        afiliacionPaciente.nroHC = long.Parse(dr["nroHCpaciente"].ToString());
                        afiliacionPaciente.nroAfiliado = long.Parse(dr["nroAfiliado"].ToString());
                        afiliacionPaciente.idAfiliacion = long.Parse(dr["idAfiliacion"].ToString());
                        afiliacionPaciente.idPlan = int.Parse(dr["idPlan"].ToString());
                        //plan de afiliacion
                        afiliacionPaciente.miPlanAfiliacion = new PlanAfiliacion();
                        afiliacionPaciente.miPlanAfiliacion.idPlan = int.Parse(dr["idPlan"].ToString());
                        afiliacionPaciente.miPlanAfiliacion.nombre = dr["nombre"].ToString();
                    }
                }
                dr.Close();

                //si obtuvimos el plan, entonces les cargamos los detalles
                if (afiliacionPaciente != null)
                {
                    comando = "SELECT idDetallePlan, idPlan, idEspecialidad, idPractica, precioAfiliado, precioMedico, nombreEspecialidad, nombrePractica, fechaVigenciaHasta, fechaVigenciaDesde "
                            + "FROM Detalle_PlanAfiliacion WHERE (idPlan = @idPlan) AND (fechaVigenciaHasta IS NULL OR fechaVigenciaHasta > GETDATE())";
                    sqlcmd = new SqlCommand(comando, conexion);
                    sqlcmd.Parameters.Add(new SqlParameter("@idPlan", afiliacionPaciente.idPlan));
                    sqlcmd.Transaction = tran;
                    dr = sqlcmd.ExecuteReader();
                    if (dr.HasRows)
                    {
                        afiliacionPaciente.miPlanAfiliacion.DetallePlanAfiliacion = new List<DetallePlanAfiliacion>();
                        DetallePlanAfiliacion objDetallePlan = null;
                        while (dr.Read())
                        {
                            objDetallePlan = new DetallePlanAfiliacion();
                            objDetallePlan.idDetallePlan = int.Parse(dr["idDetallePlan"].ToString());
                            objDetallePlan.idPlan = int.Parse(dr["idPlan"].ToString());
                            if (dr["idEspecialidad"] == DBNull.Value)
                            {
                                objDetallePlan.idEspecialidad = null;
                                objDetallePlan.nombreEspecialidad = null;
                            }
                            else
                            {
                                objDetallePlan.idEspecialidad = int.Parse(dr["idEspecialidad"].ToString());
                                objDetallePlan.nombreEspecialidad = dr["nombreEspecialidad"].ToString();
                            }
                            if (dr["idPractica"] == DBNull.Value)
                            {
                                objDetallePlan.idPractica = null;
                                objDetallePlan.nombrePractica = null;
                            }
                            else
                            {
                                objDetallePlan.idPractica = int.Parse(dr["idPractica"].ToString());
                                objDetallePlan.nombrePractica = dr["nombrePractica"].ToString();
                            }
                            objDetallePlan.fechaVigenciaDesde = DateTime.Parse(dr["fechaVigenciaDesde"].ToString());
                            if (dr["fechaVigenciaHasta"] == DBNull.Value)
                                objDetallePlan.fechaVigenciaHasta = null;
                            else
                                objDetallePlan.fechaVigenciaHasta = DateTime.Parse(dr["fechaVigenciaHasta"].ToString());
                            objDetallePlan.precioAfiliado = float.Parse(dr["precioAfiliado"].ToString());
                            objDetallePlan.precioMedico = float.Parse(dr["precioMedico"].ToString());

                            //agregamos el detalle al plan
                            afiliacionPaciente.miPlanAfiliacion.DetallePlanAfiliacion.Add(objDetallePlan);
                            objDetallePlan = null;
                        }
                    }
                    dr.Close();
                    tran.Commit();
                }
                else
                    tran.Rollback();
            }
            catch (Exception ex)
            {
                tran.Rollback();
                throw;
            }
            finally
            {
                conexion.Close();
            }
            return afiliacionPaciente;
        }


        /// <summary>
        /// Método que busca el ultimo numero de recibo generado, en caso de no encontrar, devuelve false
        /// </summary>
        /// <returns>true: si hay recibos guardados - false: no hay recibos guardados</returns>
        public static bool hayRecibo()
        {
            bool res = false;
            SqlConnection conexion = DB.Conectar();
            try
            {
                string comando = "SELECT nroSerie, nroRecibo FROM Recibo";
                SqlCommand sqlcmd = new SqlCommand(comando, conexion);
                SqlDataReader dr = sqlcmd.ExecuteReader();
                if (dr.HasRows)
                    res = true;
                else
                    res = false;
            }
            catch (Exception)
            {

                throw;
            }
            finally
            {
                conexion.Close();
            }
            return res;
        }

        //ver este metodo, porque el max de cada columna no me garantiza que sea el ultimo recibo, el ultimo recibo es el que tiene la fecha mas reciente
        //ver como se hace para saber cuál es la fecha mas reciente
        public static void ObtenerUltimoNroRecibo(out int nroSerie, out long nroRecibo)
        {
            nroRecibo = 0;
            nroSerie = 0;
            SqlConnection conexion = DB.Conectar();
            try
            {
                //este comando esta mal porque me devuelve el max de todo, y eso no necesariamente es el ultimo recibo generado
                //string comando = "SELECT MAX(nroSerie) as maxNroSerie, MAX(nroRecibo) as MaxNroRecibo FROM Recibo";

                //este comando sí valida que sea el ultimo recibo ya que verifica con la última fecha realizada.
                string comando = "SELECT nroRecibo, nroSerie FROM Recibo WHERE fecha = (select MAX(fecha) from Recibo) ";
                SqlCommand sqlcmd = new SqlCommand(comando, conexion);
                SqlDataReader dr = sqlcmd.ExecuteReader();
                if (dr.HasRows)
                {
                    while (dr.Read())
                    {
                        nroSerie = int.Parse(dr["nroSerie"].ToString());
                        nroRecibo = long.Parse(dr["nroRecibo"].ToString());
                    }
                    
                }
            }
            catch (Exception)
            {

                throw;
            }
            finally
            {
                conexion.Close();
            }
        }

        public static long ObtenerUltimoNroRecibo()
        {
            long nroRecibo = 0;
            SqlConnection conexion = DB.Conectar();
            try
            {
                //este comando esta mal porque me devuelve el max de todo, y eso no necesariamente es el ultimo recibo generado
                //string comando = "SELECT MAX(nroSerie) as maxNroSerie, MAX(nroRecibo) as MaxNroRecibo FROM Recibo";

                //este comando sí valida que sea el ultimo recibo ya que verifica con la última fecha realizada.
                string comando = "SELECT nroRecibo FROM Recibo WHERE fecha = (select MAX(fecha) from Recibo) ";
                SqlCommand sqlcmd = new SqlCommand(comando, conexion);
                SqlDataReader dr = sqlcmd.ExecuteReader();
                if (dr.HasRows)
                {
                    while (dr.Read())
                    {
                        nroRecibo = long.Parse(dr["nroRecibo"].ToString());
                    }

                }
            }
            catch (Exception)
            {

                throw;
            }
            finally
            {
                conexion.Close();
            }
            return nroRecibo;
        }



        /// <summary>
        /// Registra el cobro de la atencion medica en un recibo, validando si se ha cobrado la consulta o no,
        /// y actualizando por tanto el turno para cargarle (en caso de corresponder), el nro de recibo y el
        /// estado del turno
        /// </summary>
        /// <param name="reciboNuevo">recibo nuevo a guardar en la bd</param>
        /// <param name="idTurno">Turno para el cual se cobra la consulta</param>
        /// <param name="idEstadoTurno">Nuevo estado del turno a actualizar con el cobro</param>
        /// <param name="idEstadoTurno">Nuevo estado del turno a actualizar con el cobro</param>
        /// <returns>True: se registro correctamente - False: no se pudo registrar el recibo</returns>
        public static bool RegistrarReciboTurno(Recibo reciboNuevo, long idTurno, int idEstadoTurno, float montoMed)
        {
            bool res = false;
            SqlConnection conexion = DB.Conectar();
            SqlTransaction trans = null;
            try
            {
                trans = conexion.BeginTransaction();

                //1° insertamos el recibo
                string comando = "INSERT INTO Recibo (nroSerie, nroRecibo, fecha, subtotal, descuento, recargo, montoTotal, montoTotalLetras, nroHCpaciente, idPersonaPaciente) "
                               + "VALUES (@nroSerie,@nroRecibo,@fecha,@subtotal,@descuento,@recargo,@total,@totalLetras,@nroHC,@idPersona)";
                SqlCommand sqlcmd = new SqlCommand(comando, conexion);
                sqlcmd.Parameters.Add(new SqlParameter("@nroSerie", reciboNuevo.NroSerie));
                sqlcmd.Parameters.Add(new SqlParameter("@nroRecibo", reciboNuevo.NroRecibo));
                sqlcmd.Parameters.Add(new SqlParameter("@fecha", reciboNuevo.Fecha));
                sqlcmd.Parameters.Add(new SqlParameter("@subtotal", reciboNuevo.Subtotal));
                sqlcmd.Parameters.Add(new SqlParameter("@descuento", reciboNuevo.Descuento));
                sqlcmd.Parameters.Add(new SqlParameter("@recargo", reciboNuevo.Recargo));
                sqlcmd.Parameters.Add(new SqlParameter("@total", reciboNuevo.Total));
                sqlcmd.Parameters.Add(new SqlParameter("@totalLetras", reciboNuevo.TotalEnLetras));
                sqlcmd.Parameters.Add(new SqlParameter("@nroHC", reciboNuevo.NroHCpaciente));
                sqlcmd.Parameters.Add(new SqlParameter("@idPersona", reciboNuevo.IdPersonaPaciente));
                sqlcmd.Transaction = trans;
                int filas = sqlcmd.ExecuteNonQuery();

                //2° insertamos los detalles del recibo
                if (filas > 0)
                {
                    comando = "INSERT INTO Detalle_Recibo (nroSerieRecibo, nroRecibo, concepto, monto, idEspecialidad, idPractica) "
                            + "VALUES (@nroSerieRecibo,@nroRecibo,@concepto,@monto,@idEsp,@idPrac)";
                    foreach (DetalleRecibo item in reciboNuevo.MisDetallesRecibo)
                    {
                        sqlcmd = new SqlCommand(comando, conexion);
                        sqlcmd.Parameters.Add(new SqlParameter("@nroSerieRecibo", reciboNuevo.NroSerie));
                        sqlcmd.Parameters.Add(new SqlParameter("@nroRecibo", reciboNuevo.NroRecibo));
                        sqlcmd.Parameters.Add(new SqlParameter("@concepto", item.Concepto));
                        sqlcmd.Parameters.Add(new SqlParameter("@monto", item.Monto));
                        if (item.IdEspecialidad != null)
                            sqlcmd.Parameters.Add(new SqlParameter("@idEsp", item.IdEspecialidad));
                        else
                            sqlcmd.Parameters.Add(new SqlParameter("@idEsp", DBNull.Value));
                        if (item.IdPractica != null)
                            sqlcmd.Parameters.Add(new SqlParameter("@idPrac", item.IdPractica));
                        else
                            sqlcmd.Parameters.Add(new SqlParameter("@idPrac", DBNull.Value));
                        sqlcmd.Transaction = trans;
                        filas = sqlcmd.ExecuteNonQuery();
                    }

                    //3° actualizamos el turno, seteandole el nroRecibo de la consulta, y actualizandole el estado al turno
                    if (filas > 0)
                    {
                        comando = "UPDATE Turno SET nroSerieReciboConsulta = @nroSerie, nroReciboConsulta = @nroRecibo, idEstadoTurno = @idEstado, montoMedico = @montoMed "
                                + "WHERE (idTurno = @idTurno)";
                        sqlcmd = new SqlCommand(comando, conexion);
                        sqlcmd.Parameters.Add(new SqlParameter("@idTurno", idTurno));
                        sqlcmd.Parameters.Add(new SqlParameter("@nroSerie", reciboNuevo.NroSerie));
                        sqlcmd.Parameters.Add(new SqlParameter("@nroRecibo", reciboNuevo.NroRecibo));
                        sqlcmd.Parameters.Add(new SqlParameter("@idEstado", idEstadoTurno));
                        sqlcmd.Parameters.Add(new SqlParameter("@montoMed", montoMed));
                        sqlcmd.Transaction = trans;
                        filas = sqlcmd.ExecuteNonQuery();

                        if (filas > 0)
                        {
                            res = true;
                            trans.Commit();
                        }
                    }
                    else
                        trans.Rollback();
                }
                else
                    trans.Rollback();

            }
            catch (Exception ex)
            {
                trans.Rollback();
                throw;
            }
            finally
            {
                conexion.Close();
            }
            return res;
        }

        //registrar recibo cobro cuotas
        public static void RegistrarReciboCobroCuotas(Recibo reciboNuevo)
        {
            bool res = false;
            SqlConnection conexion = DB.Conectar();
            SqlTransaction trans = null;
            try
            {
                trans = conexion.BeginTransaction();

                //1° insertamos el recibo
                string comando = "INSERT INTO Recibo (nroSerie, nroRecibo, fecha, subtotal, recargo, montoTotal, montoTotalLetras, idInstitucion, nroAfiliado) "
                               + "VALUES (@nroSerie,@nroRecibo,@fecha,@subtotal,@recargo,@total,@totalLetras,@idInstitucion,@nroAfiliado)";
                SqlCommand sqlcmd = new SqlCommand(comando, conexion);
                sqlcmd.Parameters.Add(new SqlParameter("@nroSerie", reciboNuevo.NroSerie));
                sqlcmd.Parameters.Add(new SqlParameter("@nroRecibo", reciboNuevo.NroRecibo));
                sqlcmd.Parameters.Add(new SqlParameter("@fecha", reciboNuevo.Fecha));
                sqlcmd.Parameters.Add(new SqlParameter("@subtotal", reciboNuevo.Subtotal));
                sqlcmd.Parameters.Add(new SqlParameter("@recargo", reciboNuevo.Recargo));
                sqlcmd.Parameters.Add(new SqlParameter("@total", reciboNuevo.Total));
                sqlcmd.Parameters.Add(new SqlParameter("@totalLetras", reciboNuevo.TotalEnLetras));
                if (reciboNuevo.IdInstitucion == 0)
                {
                    sqlcmd.Parameters.Add(new SqlParameter("@idInstitucion", DBNull.Value));
                    sqlcmd.Parameters.Add(new SqlParameter("@nroAfiliado", reciboNuevo.nroAfiliado));
                }
                else
                {
                    if (reciboNuevo.nroAfiliado == 0)
                    {
                        sqlcmd.Parameters.Add(new SqlParameter("@idInstitucion", reciboNuevo.IdInstitucion));
                        sqlcmd.Parameters.Add(new SqlParameter("@nroAfiliado", DBNull.Value));

                    }


                }
                sqlcmd.Transaction = trans;
                int filas = sqlcmd.ExecuteNonQuery();

                //2° insertamos los detalles del recibo
                if (filas > 0)
                {
                    comando = "INSERT INTO Detalle_Recibo (nroSerieRecibo, nroRecibo, concepto, monto) "
                            + "VALUES (@nroSerieRecibo,@nroRecibo,@concepto,@monto)";
                    foreach (DetalleRecibo item in reciboNuevo.MisDetallesRecibo)
                    {
                        sqlcmd = new SqlCommand(comando, conexion);
                        sqlcmd.Parameters.Add(new SqlParameter("@nroSerieRecibo", reciboNuevo.NroSerie));
                        sqlcmd.Parameters.Add(new SqlParameter("@nroRecibo", reciboNuevo.NroRecibo));
                        sqlcmd.Parameters.Add(new SqlParameter("@concepto", item.Concepto));
                        sqlcmd.Parameters.Add(new SqlParameter("@monto", item.Monto));

                        sqlcmd.Transaction = trans;
                        filas = sqlcmd.ExecuteNonQuery();
                    }


                    if (filas > 0)
                    {
                        res = true;
                        trans.Commit();
                    }

                }
                else
                    trans.Rollback();

            }
            catch (Exception ex)
            {
                trans.Rollback();
                throw;
            }
            finally
            {
                conexion.Close();
            }
        }

    }
}
